package cn.bluech.lib.http;

import android.text.TextUtils;

import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.CertificatePinner;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;

/**
 * Description: Http构造器，如果不加证书工厂，https的请求默认信任所有主机
 * HttpApi server = new HttpBuilder("https://www.baidu.com/")
 *                 .build(HttpApi.class);
 * server.home()
 *       .compose(RxTransformer.io2Main())
 *       .subscribe(new Observer<ResponseBody>(){
 *            public void onSubscribe(Disposable d) { }
 *            public void onNext(ResponseBody responseBody) { }
 *            public void onError(Throwable e) { }
 *            public void onComplete() { }
 *        });
 *
 * public interface HttpApi {
 *     @GET("/")
 *     Observable<ResponseBody> home();
 *     @GET("/")
 *     Call<ResponseBody> raw();
 * }
 *
 * Create by Codeant on 2019/3/13.
 */
public class HttpBuilder {
    private Retrofit.Builder retrofitBuilder;
    private OkHttpClient.Builder clientBuilder;
    // https
    private CertificatePinner pinner; // 证书锁定
    private SSLSocketFactory sslSocketFactory; // 证书工厂
    private X509TrustManager trustManager;

    // 其它
    private boolean isHttps;

    public HttpBuilder(String baseUrl, HttpLoggingInterceptor.Level level){
        retrofitBuilder = new Retrofit.Builder();
        retrofitBuilder.baseUrl(baseUrl);
        clientBuilder = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS);
        // logger
        if (level!=HttpLoggingInterceptor.Level.NONE){
            HttpLoggingInterceptor body = new HttpLoggingInterceptor();
            body.setLevel(HttpLoggingInterceptor.Level.BODY);
            clientBuilder.addInterceptor(body);
        }

        isHttps = (!TextUtils.isEmpty(baseUrl)) && baseUrl.toLowerCase().startsWith("https://");
    }

    public HttpBuilder(String baseUrl){
        this(baseUrl,HttpLoggingInterceptor.Level.NONE);
    }

    /**
     * 拦截器
     */
    public HttpBuilder addInterceptor(Interceptor interceptor){
        if(null!=interceptor)
            clientBuilder.addInterceptor(interceptor);
        return this;
    }

    /**
     * 拦截器
     */
    public HttpBuilder addNetworkInterceptor(Interceptor interceptor){
        if(null!=interceptor)
            clientBuilder.addNetworkInterceptor(interceptor);
        return this;
    }

    /**
     * 添加证书锁定
     * 例：
     * new CertificatePinner.Builder()
     *             .add("sbbic.com", "sha1/C8xoaOSEzPC6BgGmxAt/EAcsajw=")
     *             .add("closedevice.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
     *             .build()
     */
    public HttpBuilder certificatePinner(CertificatePinner pinner){
        this.pinner = pinner;
        return this;
    }

    public HttpBuilder sslSocketFactory( SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) {
        this.sslSocketFactory = sslSocketFactory;
        this.trustManager = trustManager;
        return this;
    }

    public HttpBuilder sslSocketFactory( SSLSocketFactory sslSocketFactory){
        sslSocketFactory(sslSocketFactory,null);
        return this;
    }

    /**
     * 在HttpClient构建之前调用，用于个性化定制
     */
    protected OkHttpClient.Builder beforeClientBuild(OkHttpClient.Builder builder){
        if(null!=pinner)
            builder.certificatePinner(pinner);

        if((null!=sslSocketFactory)&&(null!=trustManager)){
            builder.sslSocketFactory(sslSocketFactory,trustManager);
        }else if(null!=sslSocketFactory){
            builder.sslSocketFactory(sslSocketFactory);
        }else if(isHttps){
            builder.sslSocketFactory(SSLFactory.ALL_TRUST);
        }
        // 主机名验证(好像是弹警告之类的)
        if(isHttps)
            builder.hostnameVerifier((hostname, session) -> true);
        return builder;
    }
    /**
     * 在Retrofit构建之前调用，用于个性化定制
     */
    protected Retrofit.Builder beforeBuild(Retrofit.Builder builder){
        builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .addConverterFactory(SimpleXmlConverterFactory.create());
        return builder;
    }

    protected Retrofit beforeCreate(Retrofit create){
        return create;
    }

    public <T> T build(Class<T> service){
        // 个性定制回调
        clientBuilder = beforeClientBuild(clientBuilder);
        retrofitBuilder.client(clientBuilder.build());
        retrofitBuilder = beforeBuild(retrofitBuilder);

        return beforeCreate(retrofitBuilder.build()).create(service);
    }
}
